package org.database.JobListenner;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.database.quartz.TaskLog;
import org.database.quartz.TaskScheduled;
import org.dynamic.config.Application;
import org.dynamic.mail.common.MailCfg;
import org.dynamic.mail.entity.MailMsg;
import org.dynamic.mail.enums.MailMsgType;
import org.dynamic.mail.service.MailService;
import org.dynamic.mail.service.impl.ApacheMailServiceImpl;
import org.dynamic.util.DateConvertUtil;
import org.dynamic.util.SpringContextUtil;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.Trigger;
import org.quartz.TriggerListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

/**
 * 任务触发器监听器
 *
 * @author huyj
 * @Created 2017-03-23 11:27
 */
public class MyTriggerListener implements TriggerListener {
    private Logger logger = LoggerFactory.getLogger(getClass());

    // 线程池
    private static ExecutorService executorService = Executors.newCachedThreadPool();

    @Override
    public String getName() {
        return "MyTriggerListener";
    }

    /**
     * (1)
     * Trigger被激发 它关联的job即将被运行
     * Called by the Scheduler when a Trigger has fired, and it's associated JobDetail is about to be executed.
     */
    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        TaskScheduled taskScheduled = (TaskScheduled) jobDataMap.get(Application.QUARTZ_DATA);
        if (logger.isInfoEnabled()) {
            logger.info("triggerFired-->Trigger被激发 它关联的job即将被运行：{}.{}    group[{}]   name[{}]", taskScheduled.getTaskTarget(), taskScheduled.getTaskMethod(), taskScheduled.getTaskGroup(), taskScheduled.getTaskName());
        }

        /*TaskLog log = (TaskLog) jobDataMap.get(Application.QUARTZ_LOG);
        try {
            log.setTask_status(context.getScheduler().getTriggerState(TriggerKey.triggerKey(taskScheduled.getTaskName(), taskScheduled.getTaskGroup())).name());
        } catch (SchedulerException e) {
            e.printStackTrace();
            logger.error("SchedulerException", e.getMessage());
        }
        log.setLog_type("triger");
        log.setExecute_starttime(new Date());
        log.setTask_desc("triggerFired Trigger被激发 它关联的job即将被运行");
        context.getJobDetail().getJobDataMap().put(Application.QUARTZ_LOG, log);
        saveLog(log);*/
    }

    /**
     * (2)
     * Trigger被激发 它关联的job即将被运行,先执行(1)，在执行(2) 如果返回TRUE 那么任务job会被终止
     * Called by the Scheduler when a Trigger has fired, and it's associated JobDetail is about to be executed
     */
    @Override
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        TaskScheduled taskScheduled = (TaskScheduled) jobDataMap.get(Application.QUARTZ_DATA);
        if (logger.isInfoEnabled()) {
            logger.info(" vetoJobExecution--> Trigger被激发 如果返回TRUE 那么任务job会被终止：{}.{}    group[{}]   name[{}]", taskScheduled.getTaskTarget(), taskScheduled.getTaskMethod(), taskScheduled.getTaskGroup(), taskScheduled.getTaskName());
        }
      /*  TaskLog log = (TaskLog) jobDataMap.get(Application.QUARTZ_LOG);
        try {
            log.setTask_status(context.getScheduler().getTriggerState(TriggerKey.triggerKey(taskScheduled.getTaskName(), taskScheduled.getTaskGroup())).name());
        } catch (SchedulerException e) {
            e.printStackTrace();
            logger.error("SchedulerException", e.getMessage());
        }
        log.setLog_type("triger");
        log.setExecute_starttime(new Date());
        log.setTask_desc("vetoJobExecution Trigger被激发 它关联的job即将被运行,先执行(1)，在执行(2) 如果返回TRUE 那么任务job会被终止");
        context.getJobDetail().getJobDataMap().put(Application.QUARTZ_LOG, log);
        saveLog(log);*/

        return false;
    }

    /**
     * (3) 当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行，但是线程池中的有效线程都在工作，
     * 那么有的触发器就有可能超时，错过这一轮的触发。
     * Called by the Scheduler when a Trigger has misfired.
     */
    @Override
    public void triggerMisfired(Trigger trigger) {
        JobDataMap jobDataMap = trigger.getJobDataMap();
        TaskScheduled taskScheduled = (TaskScheduled) jobDataMap.get(Application.QUARTZ_DATA);
        if (logger.isInfoEnabled()) {
            logger.info("triggerMisfired --> Trigger错过被激发时执行 {}.{}    group[{}]   name[{}]", taskScheduled.getTaskTarget(), taskScheduled.getTaskMethod(), taskScheduled.getTaskGroup(), taskScheduled.getTaskName());
        }

        TaskLog log = (TaskLog) jobDataMap.get(Application.QUARTZ_LOG);
        log.setLog_type("triger");
        log.setExecute_starttime(new Date());
        trigger.getJobDataMap().put(Application.QUARTZ_LOG, log);

        //发送邮件
        String info = "任务 taskGroup[" + taskScheduled.getTaskGroup() + "] , taskName[" + taskScheduled.getTaskName() + "] ,  任务描述[" + taskScheduled.getTaskDesc() + "] 于 "+ DateConvertUtil.generateDateTime(new Date(),DateConvertUtil.DATE_TIME_FORMAT)+"  错过触发时间(任务挤压)，请及时查看原因、进行调优或其他处理！\n\n可能原因： " +"当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行，但是线程池中的有效线程都在工作,那么有的触发器就有可能超时，错过这一轮的触发。";
        log.setTask_desc(info);
        sendEmail(info);

        saveLog(log);
    }

    /**
     * (4) 任务完成时触发
     * Called by the Scheduler when a Trigger has fired, it's associated JobDetail has been executed
     * and it's triggered(xx) method has been called.
     */
    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext context,
                                Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        JobDataMap jobDataMap = trigger.getJobDataMap();
        TaskScheduled taskScheduled = (TaskScheduled) jobDataMap.get(Application.QUARTZ_DATA);
        if (logger.isInfoEnabled()) {
            logger.info("triggerComplete --> triggerComplete任务完成时触发  {}.{}    group[{}]   name[{}]", taskScheduled.getTaskTarget(), taskScheduled.getTaskMethod(), taskScheduled.getTaskGroup(), taskScheduled.getTaskName());
        }
     /*   TaskLog log = (TaskLog) jobDataMap.get(Application.QUARTZ_LOG);
        try {
            log.setTask_status(context.getScheduler().getTriggerState(TriggerKey.triggerKey(taskScheduled.getTaskName(), taskScheduled.getTaskGroup())).name());
        } catch (SchedulerException e) {
            e.printStackTrace();
            logger.error("SchedulerException", e.getMessage());
        }
        log.setLog_type("triger");
        log.setExecute_starttime(new Date());
        log.setTask_desc("triggerComplete 任务完成时触发");
        trigger.getJobDataMap().put(Application.QUARTZ_LOG, log);
        saveLog(log);*/
    }


    private void sendEmail(final String content) {
        executorService.submit(new Runnable() {
            public void run() {
                MailService mailService = new ApacheMailServiceImpl();
                MailMsg msg = new MailMsg();
                msg.setType(MailMsgType.text);
                msg.setSubject("NC新系统定时任务消息");
                msg.setContent(content);
                mailService.sendMail(MailCfg.DEFAULT_TO_NAME, msg);
                //mailService.sendMail("huyj@corp.hxqc.com",msg );
            }
        });
    }


    private void saveLogThread(final TaskLog log) {
        executorService.submit(new Runnable() {
            public void run() {
                ApplicationContext app = SpringContextUtil.getApplicationContext();
//                TaskLogService taskLogService = (TaskLogService) app.getBean("taskLogService");
//                taskLogService.saveLog(log);
                log.setExecute_endtime(null);
                log.setTask_periodtime(null);
                log.setTask_desc(null);
            }
        });
    }
    private void saveLog(final TaskLog log) {
        ApplicationContext app = SpringContextUtil.getApplicationContext();
//        TaskLogService taskLogService = (TaskLogService) app.getBean("taskLogService");
//        taskLogService.saveLog(log);
        log.setExecute_endtime(null);
        log.setTask_periodtime(null);
        log.setTask_desc(null);
    }


}